/**
 * 
 */
package com.gs.gms.model.entity;

import java.io.Serializable;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.persistence.Transient;
import javax.persistence.UniqueConstraint;

import com.gs.gms.util.conerter.Conversion;
import com.gs.gms.util.conerter.FieldMapper;

/**
 * @author Sabuj Das | sabuj.das@gmail.com
 *
 */
@Entity
@Table(name="GMS_USER", uniqueConstraints={@UniqueConstraint(columnNames={"EMAIL_ADDRESS", "USER_NAME"})})
@Conversion(targetClassName="com.gs.gms.model.dto.UserDto")
public class User implements Serializable {

	/**
	 * 
	 */
	private static final long serialVersionUID = 2308183835096857109L;


	@Id @GeneratedValue(strategy=GenerationType.IDENTITY)
	@Column(name="USER_ID", unique=true, nullable=false, updatable=false)
	private Long userId;
	
	@Column(name="USER_NAME", length=50, nullable=false)
	private String userName;
	
	@Column(name="PASSWORD", length=25, nullable=false)
	private String password;
	
	@Column(name="DISPLAY_NAME", length=100, nullable=true)
	private String displayName;
	
	@Column(name="FIRST_NAME", length=100, nullable=false)
	private String firstName;
	
	@Column(name="LAST_NAME", length=100, nullable=false)
	private String lastName;
	
	@Column(name="EMAIL_ADDRESS", length=200, nullable=false)
	private String emailAddress;
	
	@Column(name="GENDER", length=1, nullable=true)
	private String gender;
	
	@Temporal(TemporalType.TIMESTAMP)
	@Column(name="DATE_OF_BIRTH", nullable=true)
	private Date dateOfBirth;
	
	@ManyToMany(cascade = CascadeType.ALL)
	@JoinTable(name = "GMS_USER_ROLE_MAP", 
		joinColumns = { @JoinColumn(name = "USER_ID") }, 
		inverseJoinColumns = { @JoinColumn(name = "ROLE_ID") })
	private Set<Role> roles = new HashSet<>(0);
	
	@OneToMany(mappedBy="user")
	private Set<UserSession> sessions = new HashSet<>(0);
	
	@OneToMany(mappedBy="sourceUser")
	private Set<UserConnection> connections = new HashSet<>(0);
	
	@Transient
	private UserSession currentSession;
	
	/**
	 * 
	 */
	public User() {
		// TODO Auto-generated constructor stub
	}


	public User(String userName, String password, String firstName,
			String lastName, String emailAddress) {
		this.userName = userName;
		this.password = password;
		this.firstName = firstName;
		this.lastName = lastName;
		this.emailAddress = emailAddress;
	}


	@FieldMapper(targetFieldName="userId")
	public Long getUserId() {
		return userId;
	}


	public void setUserId(Long userId) {
		if(null != userId){
			if(userId <= 0)
				userId = null;
		}
		this.userId = userId;
	}

	@FieldMapper(targetFieldName="userName")
	public String getUserName() {
		return userName;
	}


	public void setUserName(String userName) {
		this.userName = userName;
	}

	@FieldMapper(targetFieldName="password")
	public String getPassword() {
		return password;
	}


	public void setPassword(String password) {
		this.password = password;
	}

	@FieldMapper(targetFieldName="displayName")
	public String getDisplayName() {
		return displayName;
	}


	public void setDisplayName(String displayName) {
		this.displayName = displayName;
	}

	@FieldMapper(targetFieldName="firstName")
	public String getFirstName() {
		return firstName;
	}


	public void setFirstName(String firstName) {
		this.firstName = firstName;
	}

	@FieldMapper(targetFieldName="lastName")
	public String getLastName() {
		return lastName;
	}


	public void setLastName(String lastName) {
		this.lastName = lastName;
	}

	@FieldMapper(targetFieldName="emailAddress")
	public String getEmailAddress() {
		return emailAddress;
	}


	public void setEmailAddress(String emailAddress) {
		this.emailAddress = emailAddress;
	}

	@FieldMapper(targetFieldName="gender")
	public String getGender() {
		return gender;
	}


	public void setGender(String gender) {
		this.gender = gender;
	}

	@FieldMapper(targetFieldName="dateOfBirth")
	public Date getDateOfBirth() {
		return dateOfBirth;
	}


	public void setDateOfBirth(Date dateOfBirth) {
		this.dateOfBirth = dateOfBirth;
	}
	

	public Set<Role> getRoles() {
		return roles;
	}


	public void setRoles(Set<Role> roles) {
		this.roles = roles;
	}


	public Set<UserSession> getSessions() {
		return sessions;
	}


	public void setSessions(Set<UserSession> sessions) {
		this.sessions = sessions;
	}


	public Set<UserConnection> getConnections() {
		return connections;
	}


	public void setConnections(Set<UserConnection> connections) {
		this.connections = connections;
	}


	public void setCurrentSession(UserSession currentSession) {
		this.currentSession = currentSession;
	}


	public UserSession getCurrentSession() {
		return currentSession;
	}


	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result
				+ ((emailAddress == null) ? 0 : emailAddress.hashCode());
		result = prime * result
				+ ((userName == null) ? 0 : userName.hashCode());
		return result;
	}


	@Override
	public boolean equals(Object obj) {
		if (this == obj) {
			return true;
		}
		if (obj == null) {
			return false;
		}
		if (!(obj instanceof User)) {
			return false;
		}
		User other = (User) obj;
		if (emailAddress == null) {
			if (other.emailAddress != null) {
				return false;
			}
		} else if (!emailAddress.equals(other.emailAddress)) {
			return false;
		}
		if (userName == null) {
			if (other.userName != null) {
				return false;
			}
		} else if (!userName.equals(other.userName)) {
			return false;
		}
		return true;
	}


	@Override
	public String toString() {
		return String.format("User [userId=%s, userName=%s]", userId, userName);
	}
	
	
}
